﻿using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Reflection;
using System.Windows.Forms;
using HML;
using HML.Design;

namespace HML
{
    /// <summary>
    /// 温度计控件
    /// </summary>
    [Description("温度计控件")]
    [DefaultProperty("Value")]
    [DefaultEvent("ValueChanged")]
    [TypeConverter(typeof(PropertyOrderConverter))]
    [Designer(typeof(BorderDesigner))]
    [ToolboxItem(true)]
    [ToolboxBitmap(typeof(Thermometer), "Controls.Thermometer.Resources.Thermometer.bmp")]
    public class Thermometer : MainThreadAnimationControl, ISkinObject
    {
        #region 主题

        private SkinObjectXmlMetadata skinObjectXmlMetadata = null;
        /// <summary>
        /// 主题对象在主题文件信息
        /// </summary>
        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual SkinObjectXmlMetadata SkinObjectXmlMetadata
        {
            get
            {
                if (this.skinObjectXmlMetadata == null)
                    this.skinObjectXmlMetadata = new SkinObjectXmlMetadata(Assembly.GetAssembly(typeof(Thermometer)).GetName().Name, typeof(Thermometer).Name);

                return this.skinObjectXmlMetadata;
            }
        }

        private SkinController skinController = null;
        /// <summary>
        /// 主题控制器
        /// </summary>
        [Description("主题控制器")]
        [Category("杂项")]
        [PropertyOrder(-360)]
        [DefaultValue(null)]
        [RefreshProperties(RefreshProperties.All)]
        public virtual SkinController SkinController
        {
            get { return this.skinController; }
            set
            {
                if (this.skinController == value)
                    return;

                if (this.skinController != null)
                    this.skinController.RemoveSkinObject(this);

                this.skinController = value;

                if (this.skinController != null)
                    this.skinController.AddSkinObject(this);
            }
        }

        private SkinEnabledState skinEnabled= SkinEnabledState.Auto;
        /// <summary>
        /// 主题是否启用
        /// </summary>
        [Description("主题是否启用")]
        [Category("杂项")]
        [PropertyOrder(-300)]
        [DefaultValue(SkinEnabledState.Auto)]
        [RefreshProperties(RefreshProperties.All)]
        public virtual SkinEnabledState SkinEnabled
        {
            get { return this.skinEnabled; }
            set
            {
                if (this.skinEnabled == value)
                    return;

                this.skinEnabled = value;
                this.OnSkinChanged();
            }
        }

        private SkinStyle skinStyle = SkinStyle.Normal;
        /// <summary>
        /// 主题风格
        /// </summary>
        [Description("主题风格")]
        [Category("杂项")]
        [PropertyOrder(-260)]
        [DefaultValue(SkinStyle.Normal)]
        [RefreshProperties(RefreshProperties.All)]
        public virtual SkinStyle SkinStyle
        {
            get { return this.skinStyle; }
            set
            {
                if (this.skinStyle == value)
                    return;

                this.skinStyle = value;
                this.OnSkinChanged();
            }
        }

        private StyleAppearanceObject stateAppearance;
        /// <summary>
        /// 风格外观
        /// </summary>
        [Description("风格外观")]
        [Category("杂项")]
        [PropertyOrder(-200)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public StyleAppearanceObject StyleAppearance
        {
            get
            {
                if (this.stateAppearance == null)
                    this.stateAppearance = new StyleAppearanceObject(this, null);
                return this.stateAppearance;
            }
        }

        /// <summary>
        /// 主题已更改
        /// </summary>
        public virtual void OnSkinChanged()
        {
            SkinManager.SyncSkinValueToProperty(this);
            this.Invalidate();
        }

        private ISkinObject followSkinObject = null;
        /// <summary>
        /// 主题设置跟随指定主题对象（自己的设置不再生效，提供给代码使用）
        /// </summary>
        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [Localizable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual ISkinObject FollowSkinObject
        {
            get { return this.followSkinObject; }
            set
            {
                if (this.followSkinObject == value)
                    return;

                this.followSkinObject = value;
                this.OnSkinChanged();
            }
        }

        public virtual bool GetSkinObjectSkinStateCore()
        {
            return SkinManager.GetSkinObjectSkinState(this.FollowSkinObject ?? this);
        }

        void ISkinObject.InitializeInvalidate()
        {
            throw new NotImplementedException();
        }

        void ISkinObject.Invalidate()
        {
            this.Invalidate();
        }

        #endregion

        #region 新增事件

        private static readonly object EventValueChanged = new object();
        /// <summary>
        /// Value值更改事件
        /// </summary>
        [Description("Value值更改事件")]
        public event EventHandler ValueChanged
        {
            add { Events.AddHandler(EventValueChanged, value); }
            remove { Events.RemoveHandler(EventValueChanged, value); }
        }

        #endregion

        #region 停用事件

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler PaddingChanged
        {
            add { base.PaddingChanged += value; }
            remove { base.PaddingChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler TabIndexChanged
        {
            add { base.TabIndexChanged += value; }
            remove { base.TabIndexChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler TabStopChanged
        {
            add { base.TabStopChanged += value; }
            remove { base.TabStopChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler TextChanged
        {
            add { base.TextChanged += value; }
            remove { base.TextChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler RightToLeftChanged
        {
            add { base.RightToLeftChanged += value; }
            remove { base.RightToLeftChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler ImeModeChanged
        {
            add { base.ImeModeChanged += value; }
            remove { base.ImeModeChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler BackgroundImageChanged
        {
            add { base.BackgroundImageChanged += value; }
            remove { base.BackgroundImageChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler BackgroundImageLayoutChanged
        {
            add { base.BackgroundImageLayoutChanged += value; }
            remove { base.BackgroundImageLayoutChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler BackColorChanged
        {
            add { base.BackColorChanged += value; }
            remove { base.BackColorChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler ForeColorChanged
        {
            add { base.ForeColorChanged += value; }
            remove { base.ForeColorChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler Click
        {
            add { base.Click += value; }
            remove { base.Click -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler DoubleClick
        {
            add { base.DoubleClick += value; }
            remove { base.DoubleClick -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event MouseEventHandler MouseClick
        {
            add { base.MouseClick += value; }
            remove { base.MouseClick -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event MouseEventHandler MouseDoubleClick
        {
            add { base.MouseDoubleClick += value; }
            remove { base.MouseDoubleClick -= value; }
        }

        #endregion

        #region 新增属性

        private bool animationEnabled = false;
        /// <summary>
        /// Value改变时是否采用动画方式
        /// </summary>
        [Description("Value改变时是否采用动画方式")]
        [Category("杂项")]
        [PropertyOrder(-198)]
        [DefaultValue(false)]
        public bool AnimationEnabled
        {
            get { return this.animationEnabled; }
            set
            {
                if (this.animationEnabled == value)
                    return;

                this.animationEnabled = value;
                if (!this.animationEnabled)
                {
                    this.animation_current_value = this.Value;
                    MainThreadAnimationControl.AnimationStop(this);
                    this.Invalidate();
                }
            }
        }

        private int animationTime = 100;
        /// <summary>
        /// Value改变时使用动画的时间(毫秒)
        /// </summary>
        [Description("Value改变时使用动画的时间(毫秒)")]
        [Category("杂项")]
        [PropertyOrder(-197)]
        [DefaultValue(100)]
        public int AnimationTime
        {
            get { return this.animationTime; }
            set
            {
                if (this.animationTime == value || value <= 0)
                    return;

                this.animationTime = value;
            }
        }

        private PipeObject pipe;
        /// <summary>
        /// 玻璃管
        /// </summary>
        [Description("玻璃管")]
        [Category("杂项")]
        [PropertyOrder(-195)]
        [DefaultValue(null)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public PipeObject Pipe
        {
            get
            {
                if (this.pipe == null)
                    this.pipe = new PipeObject(this);
                return this.pipe;
            }
        }

        private MarkObject mark;
        /// <summary>
        /// 刻度
        /// </summary>
        [Description("刻度")]
        [Category("杂项")]
        [PropertyOrder(-193)]
        [DefaultValue(null)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public MarkObject Mark
        {
            get
            {
                if (this.mark == null)
                    this.mark = new MarkObject(this);
                return this.mark;
            }
        }

        private double maxValue = 100D;
        /// <summary>
        /// 最大值
        /// </summary>
        [Description("最大值")]
        [Category("杂项")]
        [PropertyOrder(-191)]
        [DefaultValue(100D)]
        public double MaxValue
        {
            get { return this.maxValue; }
            set
            {
                if (this.maxValue == value)
                    return;

                this.maxValue = value;
                if (value < this.minValue)
                {
                    this.minValue = value;
                }
                if (this.value < this.minValue)
                {
                    this.value = this.minValue;
                }
                if (this.value > this.maxValue)
                {
                    this.value = this.maxValue;
                }

                this.animation_current_value = this.Value;
                MainThreadAnimationControl.AnimationStop(this);
                this.InitializeElement();
                this.Invalidate();
            }
        }

        private double minValue = 0D;
        /// <summary>
        /// 最小值
        /// </summary>
        [Description("最小值")]
        [Category("杂项")]
        [PropertyOrder(-188)]
        [DefaultValue(0D)]
        public double MinValue
        {
            get { return this.minValue; }
            set
            {
                if (this.minValue == value)
                    return;

                this.minValue = value;
                if (value > this.maxValue)
                {
                    this.maxValue = value;
                }
                if (this.value < this.minValue)
                {
                    this.value = this.minValue;
                }
                if (this.value > this.maxValue)
                {
                    this.value = this.maxValue;
                }

                this.animation_current_value = this.Value;
                MainThreadAnimationControl.AnimationStop(this);
                this.InitializeElement();
                this.Invalidate();
            }
        }

        private double value = 0D;
        /// <summary>
        /// 值
        /// </summary>
        [Description("值")]
        [Category("杂项")]
        [PropertyOrder(-186)]
        [DefaultValue(0D)]
        public double Value
        {
            get { return this.value; }
            set
            {
                value = Math.Min(value, this.MaxValue);
                value = Math.Max(value, this.MinValue);
                if (this.value == value)
                    return;

                this.value = value;
                if (this.AnimationEnabled && this.Enabled && this.Visible && this.DesignMode == false && this.Parent != null)
                {
                    this.animation_start_value = this.animation_current_value;
                    this.animation_current_value = this.animation_start_value;
                    this.animation_end_value = value;

                    this.usedTime = 0;
                    MainThreadAnimationControl.AnimationStart(this);
                    this.Invalidate();
                }
                else
                {
                    this.animation_current_value = value;
                    this.Invalidate();
                }

                this.OnValueChanged(EventArgs.Empty);
            }
        }

        #endregion

        #region 重写属性

        protected override Size DefaultSize
        {
            get { return new Size(45, 160); }
        }

        protected override ImeMode DefaultImeMode
        {
            get { return ImeMode.Disable; }
        }

        #endregion

        #region 停用属性

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new Padding Padding
        {
            get { return base.Padding; }
            set { base.Padding = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new int TabIndex
        {
            get { return base.TabIndex; }
            set { base.TabIndex = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new bool TabStop
        {
            get { return base.TabStop; }
            set { base.TabStop = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public override RightToLeft RightToLeft
        {
            get { return base.RightToLeft; }
            set { base.RightToLeft = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new ImeMode ImeMode
        {
            get { return base.ImeMode; }
            set { base.ImeMode = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public override string Text
        {
            get { return base.Text; }
            set { base.Text = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new Image BackgroundImage
        {
            get { return base.BackgroundImage; }
            set { base.BackgroundImage = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new ImageLayout BackgroundImageLayout
        {
            get { return base.BackgroundImageLayout; }
            set { base.BackgroundImageLayout = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public override Color BackColor
        {
            get { return this.StyleAppearance.BackColor; }
            set { }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public override Color ForeColor
        {
            get { return this.StyleAppearance.TextColor; }
            set { }
        }

        #endregion

        #region 字段

        /// <summary>
        /// 玻璃管rect(排除顶部圆角和底部玻璃球部分)
        /// </summary>
        private RectangleF pipeRect = RectangleF.Empty;
        /// <summary>
        /// 玻璃球rect
        /// </summary>
        private RectangleF ballRect = RectangleF.Empty;

        /// <summary>
        /// 动画开始值
        /// </summary>
        private double animation_start_value = 0f;
        /// <summary>
        /// 动画结束值
        /// </summary>
        private double animation_end_value = 0f;
        /// <summary>
        /// 动画当前值
        /// </summary>
        private double animation_current_value = 0f;
        /// <summary>
        /// 动画已使用的时间
        /// </summary>
        private double usedTime = 0;

        /// <summary>
        /// 内容内边距
        /// </summary>
        private int content_padding = 2;

        #endregion

        public Thermometer()
        {
            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            SetStyle(ControlStyles.SupportsTransparentBackColor, true);
            SetStyle(ControlStyles.ResizeRedraw, true);
            SetStyle(ControlStyles.StandardClick, false);
            SetStyle(ControlStyles.StandardDoubleClick, false);
            SetStyle(ControlStyles.Selectable, false);

            this.TabStop = false;
            this.InitializeElement();
            this.OnSkinChanged();

        }

        #region 重写

        protected override void OnScaleDpiChangedInitialize()
        {
            this.InitializeElement();
            this.Invalidate();
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            Graphics g = e.Graphics;

            int scale_pipeborder_radius = (int)Math.Ceiling(this.Pipe.BorderThickness * this.ScaleDpi);
            int scale_pipeborder_diameter = scale_pipeborder_radius * 2;
            decimal maxminvalue_scope = (decimal)this.MaxValue - (decimal)this.MinValue;//最大值与最小值的有效范围长度

            GraphicsPath pipe_back_gp = new GraphicsPath();
            pipe_back_gp.AddArc(this.ballRect, 360 - this.Pipe.CosAngle, 180 + this.Pipe.CosAngle * 2);
            pipe_back_gp.AddArc(new RectangleF(this.pipeRect.X, this.pipeRect.Y - this.pipeRect.Width / 2, this.pipeRect.Width, this.pipeRect.Width), 180, 180);
            pipe_back_gp.CloseFigure();

            GraphicsPath pipe_value_gp = new GraphicsPath();
            pipe_value_gp.AddArc(this.ballRect, 360 - this.Pipe.CosAngle, 180 + this.Pipe.CosAngle * 2);
            if (this.animation_current_value < this.MaxValue)
            {
                float y = (int)(this.pipeRect.Bottom - this.pipeRect.Height * (float)(((decimal)this.animation_current_value - (decimal)this.MinValue) / maxminvalue_scope));
                pipe_value_gp.AddLine(new PointF(this.pipeRect.X, y), new PointF(this.pipeRect.Right, y));
            }
            else
            {
                pipe_value_gp.AddArc(new RectangleF(this.pipeRect.X, this.pipeRect.Y - this.pipeRect.Width / 2, this.pipeRect.Width, this.pipeRect.Width), 180, 180);
            }
            pipe_value_gp.CloseFigure();

            g.SmoothingMode = SmoothingMode.AntiAlias;

            // 玻璃管内背景色
            SolidBrush pipe_back_sb = new SolidBrush(this.StyleAppearance.Pipe.BackColor);
            g.FillPath(pipe_back_sb, pipe_back_gp);
            pipe_back_sb.Dispose();

            // 值颜色
            SolidBrush pipe_value_sb = new SolidBrush(this.StyleAppearance.Pipe.ValueColor);
            g.FillPath(pipe_value_sb, pipe_value_gp);
            pipe_value_sb.Dispose();

            //边框
            if (scale_pipeborder_diameter > 0)
            {
                Pen border_pen = new Pen(this.StyleAppearance.Pipe.BorderColor, scale_pipeborder_radius);
                g.DrawPath(border_pen, pipe_back_gp);
                border_pen.Dispose();
            }

            pipe_back_gp.Dispose();
            pipe_value_gp.Dispose();

            //  刻度
            if (this.Mark.Visible)
            {
                g.SmoothingMode = SmoothingMode.Default;

                int scale_markMainLineThickness = (int)Math.Ceiling(this.Mark.MainLineThickness * this.ScaleDpi);
                Pen mainLine_pen = new Pen(this.StyleAppearance.Mark.MainLineColor, 2);
                Pen minorLine_pen = this.Mark.MinorAmount > 1 ? new Pen(this.StyleAppearance.Mark.MinorLineColor, 2) : null;
                SolidBrush mainLineText_sb = this.Mark.MainLineTextVisible ? new SolidBrush(this.StyleAppearance.TextColor) : null;

                decimal maxValue_offset_value = (decimal)Math.Abs(this.MaxValue % this.Mark.MainFrequency);
                decimal minValue_offset_value = (decimal)Math.Abs(this.MinValue % this.Mark.MainFrequency);

                int mainLine_count = (int)((maxminvalue_scope) / (decimal)this.Mark.MainFrequency) + 1;//分了多少个主刻度
                decimal main_representative_pixel = (decimal)this.pipeRect.Height / maxminvalue_scope * (decimal)this.Mark.MainFrequency;//一个主刻度代表多少个像素
                decimal mainLine_y_start = (decimal)this.pipeRect.Bottom;//第一个主刻度开始y坐标
                if (minValue_offset_value != 0)
                {
                    mainLine_y_start -= ((decimal)this.Mark.MainFrequency - minValue_offset_value) / (decimal)this.Mark.MainFrequency * main_representative_pixel;
                }

                float mainLine_x_start = this.pipeRect.Right + scale_pipeborder_radius;
                float mainLine_x_end = this.pipeRect.Right + scale_pipeborder_radius + scale_markMainLineThickness;
                float minorLine_x_start = this.pipeRect.Right + scale_pipeborder_radius;
                float minorLine_x_end = this.pipeRect.Right + scale_pipeborder_radius + scale_markMainLineThickness / 5 * 3;
                if (this.Mark.Alignment == ThermometerMarkAlignment.Left)
                {
                    mainLine_x_start = this.pipeRect.X - scale_pipeborder_radius;
                    mainLine_x_end = this.pipeRect.X - scale_pipeborder_radius - scale_markMainLineThickness;
                    minorLine_x_start = this.pipeRect.X - scale_pipeborder_radius;
                    minorLine_x_end = this.pipeRect.X - scale_pipeborder_radius - scale_markMainLineThickness / 5 * 3;
                }

                NativeMethods.TEXTMETRIC? font_metrics = null;
                for (int i = 0; i <= mainLine_count; i++)
                {
                    //主刻度线
                    mainLine_y_start -= (i == 0 ? 0 : main_representative_pixel);
                    g.DrawLine(mainLine_pen, mainLine_x_start, (float)mainLine_y_start, mainLine_x_end, (float)mainLine_y_start);

                    //主刻度值
                    if (this.Mark.MainLineTextVisible)
                    {
                        if (font_metrics == null)
                        {
                            font_metrics = ControlHelper.GetFontMetrics(this.Handle, this.Font);
                        }
                        decimal mainLine_value = (decimal)this.MinValue;
                        if (minValue_offset_value != 0)
                        {
                            mainLine_value += ((decimal)this.Mark.MainFrequency - minValue_offset_value);
                        }
                        mainLine_value += i * (decimal)this.Mark.MainFrequency;
                        string mainLine_str = mainLine_value.ToString();
                        SizeF str_size = new SizeF(g.MeasureString(mainLine_str, this.Font, int.MaxValue, StringFormat.GenericTypographic).Width, font_metrics.Value.GetFontRealHeight());
                        float mainLine_text_x_strat = (this.Mark.Alignment == ThermometerMarkAlignment.Left) ? (mainLine_x_end - str_size.Width) : mainLine_x_end;
                        g.DrawString(mainLine_str, this.Font, mainLineText_sb, mainLine_text_x_strat, ((float)mainLine_y_start - str_size.Height / 2f), StringFormat.GenericTypographic);
                    }

                    //子刻度线
                    if (this.Mark.MinorAmount > 1)
                    {
                        decimal minorLine_y_start = mainLine_y_start;
                        for (int j = 0; j < this.Mark.MinorAmount - 1; j++)
                        {
                            minorLine_y_start -= main_representative_pixel / this.Mark.MinorAmount;
                            if (minorLine_y_start < (decimal)this.pipeRect.Y)
                            {
                                break;
                            }
                            g.DrawLine(minorLine_pen, minorLine_x_start, (float)minorLine_y_start, minorLine_x_end, (float)minorLine_y_start);
                        }
                    }

                }
                if (minValue_offset_value != 0)
                {
                    decimal minorLine_y_start = (decimal)this.pipeRect.Bottom - minValue_offset_value / (decimal)this.Mark.MainFrequency * main_representative_pixel;//第一个主刻度开始y坐标
                    for (int j = 0; j < this.Mark.MinorAmount - 1; j++)
                    {
                        minorLine_y_start += main_representative_pixel / this.Mark.MinorAmount;
                        if (minorLine_y_start > (decimal)this.pipeRect.Bottom)
                        {
                            break;
                        }
                        g.DrawLine(minorLine_pen, minorLine_x_start, (float)minorLine_y_start, minorLine_x_end, (float)minorLine_y_start);
                    }
                }


                mainLine_pen.Dispose();
                if (mainLineText_sb != null)
                    mainLineText_sb.Dispose();
                if (minorLine_pen != null)
                    minorLine_pen.Dispose();
            }

        }

        protected override void OnEnabledChanged(EventArgs e)
        {
            base.OnEnabledChanged(e);

            if (this.DesignMode)
                return;

            if (!this.Enabled)
            {
                this.animation_current_value = this.Value;
                MainThreadAnimationControl.AnimationStop(this);
            }
        }

        protected override void OnVisibleChanged(EventArgs e)
        {
            base.OnVisibleChanged(e);

            if (this.DesignMode)
                return;

            if (!this.Visible)
            {
                this.animation_current_value = this.Value;
                MainThreadAnimationControl.AnimationStop(this);
            }
        }

        protected override void OnParentChanged(EventArgs e)
        {
            base.OnParentChanged(e);

            if (this.DesignMode)
                return;

            if (!this.Visible)
            {
                this.animation_current_value = this.Value;
                MainThreadAnimationControl.AnimationStop(this);
            }
        }

        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);

            this.InitializeElement();
            this.Invalidate();
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                MainThreadAnimationControl.AnimationStop(this);
            }
            base.Dispose(disposing);
        }

        /// <summary>
        /// 动画控件动画中要处理的内容(不能时耗时操作)
        /// </summary>
        /// <param name="interval">动画定时器间隔时间</param>
        protected override void Animationing(int interval)
        {
            bool finish = false;
            this.usedTime += interval;
            if (this.usedTime > this.AnimationTime)
            {
                this.usedTime = this.AnimationTime;
                MainThreadAnimationControl.AnimationStop(this);
                finish = true;
            }

            double progress = this.usedTime / AnimationTime;
            if (finish)
            {
                if (progress < 0)
                    progress = 0;
                if (progress > 1)
                    progress = 1;

                this.usedTime = 0;
            }

            this.animation_current_value = this.animation_start_value + (this.animation_end_value - this.animation_start_value) * progress;
            this.Invalidate();
        }

        #endregion

        #region 虚方法

        protected virtual void OnValueChanged(EventArgs e)
        {
            EventHandler handler = Events[EventValueChanged] as EventHandler;
            if (handler != null)
            {
                handler(this, e);
            }
        }

        #endregion

        #region 公开方法

        /// <summary>
        /// 初始化控件内部元素布局
        /// </summary>
        public void InitializeElement()
        {
            int scale_content_padding = (int)Math.Ceiling(this.content_padding * this.ScaleDpi);
            Rectangle content_rect = new Rectangle(this.ClientRectangle.X + scale_content_padding, this.ClientRectangle.Y + scale_content_padding, this.ClientRectangle.Width - scale_content_padding * 2, this.ClientRectangle.Height - scale_content_padding * 2);
            int scale_pipeborder_radius = (int)(Math.Ceiling(this.Pipe.BorderThickness * this.ScaleDpi) / 2);
            int scale_pipeborder_diameter = scale_pipeborder_radius * 2;
            int scale_pipe_radius = (int)(Math.Ceiling(this.Pipe.Diameter * this.ScaleDpi) / 2);//温度计玻璃管半径
            int scale_pipe_diameter = scale_pipe_radius * 2;
            float scale_ball_radius = scale_pipe_radius / (float)Math.Cos(Math.PI / 180 * this.Pipe.CosAngle);//温度计球半径
            float scale_ball_pipe_offset = scale_ball_radius - (float)Math.Sqrt(scale_ball_radius * scale_ball_radius - scale_pipe_radius * scale_pipe_radius);//温度计玻璃管底部往温度计球顶部往下偏移量

            RectangleF pipe_rect = new RectangleF(content_rect.Right - scale_pipeborder_radius - scale_ball_radius - scale_pipe_radius, content_rect.Y + scale_pipeborder_radius + scale_pipe_radius, scale_pipe_diameter, content_rect.Height - scale_pipeborder_diameter - scale_pipe_radius - scale_ball_radius * 2 + scale_ball_pipe_offset);
            if (this.Mark.Alignment == ThermometerMarkAlignment.Right)
            {
                pipe_rect.X = content_rect.X + scale_pipeborder_radius + (scale_ball_radius - scale_pipe_radius);
            }
            this.pipeRect = pipe_rect;

            this.ballRect = new RectangleF(pipe_rect.X - (scale_ball_radius - scale_pipe_radius), pipe_rect.Bottom - scale_ball_pipe_offset, scale_ball_radius * 2, scale_ball_radius * 2);

        }

        #endregion

        #region 类

        [TypeConverter(typeof(PropertyOrderConverter))]
        public class PipeObject
        {
            private Thermometer owner = null;
            internal PipeObject(Thermometer owner) { this.owner = owner; }

            #region 属性

            private int borderThickness = 1;
            /// <summary>
            /// 玻璃管边框厚度
            /// </summary>
            [Description("玻璃管边框厚度")]
            [PropertyOrder(-196)]
            [DefaultValue(1)]
            public int BorderThickness
            {
                get { return this.borderThickness; }
                set
                {
                    if (this.borderThickness == value || value < 0)
                        return;

                    this.borderThickness = value;
                    if (this.owner != null)
                    {
                        this.owner.InitializeElement();
                        this.owner.Invalidate();
                    }
                }
            }

            private int diameter = 10;
            /// <summary>
            /// 玻璃管直径
            /// </summary>
            [Description("玻璃管直径")]
            [Category("杂项_玻璃管")]
            [PropertyOrder(-188)]
            [DefaultValue(10)]
            public int Diameter
            {
                get { return this.diameter; }
                set
                {
                    if (this.diameter == value)
                        return;

                    this.diameter = value;
                    if (this.owner != null)
                    {
                        this.owner.InitializeElement();
                        this.owner.Invalidate();
                    }
                }
            }

            private int cosAngle = 55;
            /// <summary>
            /// 玻璃泡半径（相对于玻璃管半径cos函数计算 》0 《80）
            /// </summary>
            [Description("玻璃泡半径（相对于玻璃管半径cos函数计算 》0 《80）")]
            [PropertyOrder(-186)]
            [DefaultValue(55)]
            public int CosAngle
            {
                get { return this.cosAngle; }
                set
                {
                    if (this.cosAngle == value || value <= 0 || value >= 90)
                        return;

                    this.cosAngle = value;
                    if (this.owner != null)
                    {
                        this.owner.InitializeElement();
                        this.owner.Invalidate();
                    }
                }
            }

            #endregion

        }

        [TypeConverter(typeof(PropertyOrderConverter))]
        public class MarkObject
        {
            private Thermometer owner = null;
            internal MarkObject(Thermometer owner) { this.owner = owner; }

            #region 属性

            private bool visible = true;
            /// <summary>
            /// 是否显示刻度线
            /// </summary>
            [Description("是否显示刻度线")]
            [PropertyOrder(-179)]
            [DefaultValue(true)]
            public bool Visible
            {
                get { return this.visible; }
                set
                {
                    if (this.visible == value)
                        return;

                    this.visible = value;
                    if (this.owner != null)
                    {
                        this.owner.InitializeElement();
                        this.owner.Invalidate();
                    }
                }
            }

            private ThermometerMarkAlignment alignment = ThermometerMarkAlignment.Left;
            /// <summary>
            /// 刻度线对齐方式
            /// </summary>
            [Description("刻度线对齐方式")]
            [PropertyOrder(-178)]
            [DefaultValue(ThermometerMarkAlignment.Left)]
            public ThermometerMarkAlignment Alignment
            {
                get { return this.alignment; }
                set
                {
                    if (this.alignment == value)
                        return;

                    this.alignment = value;
                    if (this.owner != null)
                    {
                        this.owner.InitializeElement();
                        this.owner.Invalidate();
                    }
                }
            }

            private double mainFrequency = 10D;
            /// <summary>
            /// 主刻度线间隔值
            /// </summary>
            [Description("主刻度线间隔值")]
            [PropertyOrder(-177)]
            [DefaultValue(10D)]
            public double MainFrequency
            {
                get { return this.mainFrequency; }
                set
                {
                    if (this.mainFrequency == value || value < 0d)
                        return;

                    this.mainFrequency = value;
                    if (this.owner != null)
                    {
                        this.owner.InitializeElement();
                        this.owner.Invalidate();
                    }
                }
            }

            private int mainLineThickness = 6;
            /// <summary>
            /// 主刻度线长度
            /// </summary>
            [Description("主刻度线长度")]
            [PropertyOrder(-175)]
            [DefaultValue(6)]
            public int MainLineThickness
            {
                get { return this.mainLineThickness; }
                set
                {
                    if (this.mainLineThickness == value)
                        return;

                    this.mainLineThickness = value;
                    if (this.owner != null)
                    {
                        this.owner.InitializeElement();
                        this.owner.Invalidate();
                    }
                }
            }

            private bool mainLineTextVisible = true;
            /// <summary>
            /// 是否显示主刻度线文本
            /// </summary>
            [Description("是否显示主刻度线文本")]
            [PropertyOrder(-172)]
            [DefaultValue(true)]
            public bool MainLineTextVisible
            {
                get { return this.mainLineTextVisible; }
                set
                {
                    if (this.mainLineTextVisible == value)
                        return;

                    this.mainLineTextVisible = value;
                    if (this.owner != null)
                    {
                        this.owner.InitializeElement();
                        this.owner.Invalidate();
                    }
                }
            }

            private int minorAmount = 1;
            /// <summary>
            /// 一个主刻度分割成多少个子刻度
            /// </summary>
            [Description("一个主刻度分割成多少个子刻度")]
            [PropertyOrder(-166)]
            [DefaultValue(1)]
            public int MinorAmount
            {
                get { return this.minorAmount; }
                set
                {
                    if (this.minorAmount == value || value < 1)
                        return;

                    this.minorAmount = value;
                    if (this.owner != null)
                    {
                        this.owner.Invalidate();
                    }
                }
            }

            #endregion

        }

        #endregion

        #region 外观

        public class StyleAppearanceObject : AppearanceObjectBase
        {
            internal StyleAppearanceObject(ISkinObject owner, AppearanceObjectBase parent) : base(owner, parent) { }

            #region 属性

            private Color skinBackColor = Color.Empty;
            private readonly Color defaultBackColor = SystemColors.Control;
            private Color backColor = Color.Empty;
            /// <summary>
            /// 背景颜色
            /// </summary>
            [Description("背景颜色")]
            [PropertyOrder(-195)]
            [SkinProperty(true, true)]
            public Color BackColor
            {
                get
                {
                    if (this.owner.GetSkinObjectSkinStateCore() && this.skinBackColor != Color.Empty)
                    {
                        return this.skinBackColor;
                    }

                    if (this.backColor != Color.Empty)
                    {
                        return this.backColor;
                    }

                    if (((Control)this.owner).Parent != null)
                    {
                        return ((Control)this.owner).Parent.BackColor;
                    }

                    return this.defaultBackColor;
                }
                set
                {
                    if (this.backColor == value)
                        return;

                    this.backColor = value;
                    this.Invalidate();
                }
            }
            private bool ShouldSerializeBackColor()
            {
                return this.backColor != Color.Empty;
            }
            private void ResetBackColor()
            {
                this.backColor = Color.Empty;
                this.Invalidate();
            }

            private Color skinTextColor = Color.Empty;
            private readonly Color defaultTextColor = SystemColors.ControlText;
            private Color textColor = Color.Empty;
            /// <summary>
            /// 文本颜色
            /// </summary>
            [Description("文本颜色")]
            [PropertyOrder(-193)]
            [SkinProperty(true, true)]
            public Color TextColor
            {
                get
                {
                    if (this.owner.GetSkinObjectSkinStateCore() && this.skinTextColor != Color.Empty)
                    {
                        return this.skinTextColor;
                    }

                    if (this.textColor != Color.Empty)
                    {
                        return this.textColor;
                    }

                    if (((Control)this.owner).Parent != null)
                    {
                        return ((Control)this.owner).Parent.ForeColor;
                    }

                    return this.defaultTextColor;
                }
                set
                {
                    if (this.textColor == value)
                        return;

                    this.textColor = value;
                    this.Invalidate();
                }
            }
            private bool ShouldSerializeTextColor()
            {
                return this.textColor != Color.Empty;
            }
            private void ResetTextColor()
            {
                this.textColor = Color.Empty;
                this.Invalidate();
            }

            private PipeAppearanceObject pipe;
            /// <summary>
            /// 玻璃管
            /// </summary>
            [Description("玻璃管")]
            [PropertyOrder(-190)]
            [DefaultValue(null)]
            [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
            [SkinProperty(true, false)]
            public PipeAppearanceObject Pipe
            {
                get
                {
                    if (this.pipe == null)
                        this.pipe = new PipeAppearanceObject(this.owner, this);
                    return this.pipe;
                }
            }

            private MarkAppearanceObject mark;
            /// <summary>
            /// 刻度
            /// </summary>
            [Description("刻度")]
            [PropertyOrder(-188)]
            [DefaultValue(null)]
            [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
            [SkinProperty(true, false)]
            public MarkAppearanceObject Mark
            {
                get
                {
                    if (this.mark == null)
                        this.mark = new MarkAppearanceObject(this.owner, this);
                    return this.mark;
                }
            }

            #endregion

            public class PipeAppearanceObject : AppearanceObjectBase
            {
                internal PipeAppearanceObject(ISkinObject owner, AppearanceObjectBase parent) : base(owner, parent) { }

                #region 属性

                private Color skinBorderColor = Color.Empty;
                private readonly Color defaultBorderColor = SystemColors.ActiveCaption;
                private Color borderColor = Color.Empty;
                /// <summary>
                /// 玻璃管边框颜色
                /// </summary>
                [Description("玻璃管边框颜色")]
                [PropertyOrder(-198)]
                [SkinProperty(true, false)]
                public Color BorderColor
                {
                    get
                    {
                        if (this.owner.GetSkinObjectSkinStateCore())
                        {
                            return this.skinBorderColor;
                        }

                        if (this.borderColor != Color.Empty)
                        {
                            return this.borderColor;
                        }

                        return this.defaultBorderColor;
                    }
                    set
                    {
                        if (this.borderColor == value)
                            return;

                        this.borderColor = value;
                        this.Invalidate();
                    }
                }
                private bool ShouldSerializeBorderColor()
                {
                    return this.borderColor != Color.Empty;
                }
                private void ResetBorderColor()
                {
                    this.borderColor = Color.Empty;
                    this.Invalidate();
                }

                private Color skinBackColor = Color.Empty;
                private readonly Color defaultBackColor = SystemColors.Window;
                private Color backColor = Color.Empty;
                /// <summary>
                /// 玻璃管内背景颜色
                /// </summary>
                [Description("玻璃管内背景颜色")]
                [PropertyOrder(-196)]
                [SkinProperty(true, false)]
                public Color BackColor
                {
                    get
                    {
                        if (this.owner.GetSkinObjectSkinStateCore())
                        {
                            return this.skinBackColor;
                        }

                        if (this.backColor != Color.Empty)
                        {
                            return this.backColor;
                        }

                        return this.defaultBackColor;
                    }
                    set
                    {
                        if (this.backColor == value)
                            return;

                        this.backColor = value;
                        this.Invalidate();
                    }
                }
                private bool ShouldSerializeBackColor()
                {
                    return this.backColor != Color.Empty;
                }
                private void ResetBackColor()
                {
                    this.backColor = Color.Empty;
                    this.Invalidate();
                }

                private Color skinValueColor = Color.Empty;
                private readonly Color defaultValueColor = Color.Tomato;
                private Color valueColor = Color.Empty;
                /// <summary>
                /// 玻璃管值颜色
                /// </summary>
                [Description("玻璃管值颜色")]
                [PropertyOrder(-180)]
                [SkinProperty(true, false)]
                public Color ValueColor
                {
                    get
                    {
                        if (this.owner.GetSkinObjectSkinStateCore())
                        {
                            return this.skinValueColor;
                        }

                        if (this.valueColor != Color.Empty)
                        {
                            return this.valueColor;
                        }

                        return this.defaultValueColor;
                    }
                    set
                    {
                        if (this.valueColor == value)
                            return;

                        this.valueColor = value;
                        this.Invalidate();
                    }
                }
                private bool ShouldSerializeValueColor()
                {
                    return this.valueColor != Color.Empty;
                }
                private void ResetValueColor()
                {
                    this.valueColor = Color.Empty;
                    this.Invalidate();
                }

                #endregion

            }

            public class MarkAppearanceObject : AppearanceObjectBase
            {
                internal MarkAppearanceObject(ISkinObject owner, AppearanceObjectBase parent) : base(owner, parent) { }

                #region 属性

                private Color skinMainLineColor = Color.Empty;
                private readonly Color defaultMainLineColor = SystemColors.ActiveCaption;
                private Color mainLineColor = Color.Empty;
                /// <summary>
                /// 主刻度线颜色
                /// </summary>
                [Description("主刻度线颜色")]
                [PropertyOrder(-174)]
                [SkinProperty(true, true)]
                public Color MainLineColor
                {
                    get
                    {
                        if (this.owner.GetSkinObjectSkinStateCore() && this.skinMainLineColor != Color.Empty)
                        {
                            return this.skinMainLineColor;
                        }

                        if (this.mainLineColor != Color.Empty)
                        {
                            return this.mainLineColor;
                        }

                        if (((Control)this.owner).Parent != null)
                        {
                            return ((Control)this.owner).Parent.ForeColor;
                        }

                        return this.defaultMainLineColor;
                    }
                    set
                    {
                        if (this.mainLineColor == value)
                            return;

                        this.mainLineColor = value;
                        this.Invalidate();
                    }
                }
                private bool ShouldSerializeMainLineColor()
                {
                    return this.mainLineColor != Color.Empty;
                }
                private void ResetMainLineColor()
                {
                    this.mainLineColor = Color.Empty;
                    this.Invalidate();
                }

                private Color skinMinorLineColor = Color.Empty;
                private readonly Color defaultMinorLineColor = SystemColors.ActiveCaption;
                private Color minorLineColor = Color.Empty;
                /// <summary>
                /// 子刻度颜色
                /// </summary>
                [Description("子刻度颜色")]
                [PropertyOrder(-164)]
                [SkinProperty(true, true)]
                public Color MinorLineColor
                {
                    get
                    {
                        if (this.owner.GetSkinObjectSkinStateCore() && this.skinMinorLineColor != Color.Empty)
                        {
                            return this.skinMinorLineColor;
                        }

                        if (this.minorLineColor != Color.Empty)
                        {
                            return this.minorLineColor;
                        }

                        if (((Control)this.owner).Parent != null)
                        {
                            return ((Control)this.owner).Parent.ForeColor;
                        }

                        return this.defaultMinorLineColor;
                    }
                    set
                    {
                        if (this.minorLineColor == value)
                            return;

                        this.minorLineColor = value;
                        this.Invalidate();
                    }
                }
                private bool ShouldSerializeMinorLineColor()
                {
                    return this.minorLineColor != Color.Empty;
                }
                private void ResetMinorLineColor()
                {
                    this.minorLineColor = Color.Empty;
                    this.Invalidate();
                }
                #endregion

            }
        }

        #endregion

    }
}
